package com.un.ebs.businessObject.service.impl;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.un.ebs.businessObject.dto.TableView;
import com.un.ebs.businessObject.service.DataSourceService;
import com.un.ebs.businessObject.service.DbService;
import com.un.ebs.businessObject.service.RelService;
import com.un.ebs.businessObject.service.SQLStrategy;
import com.un.ebs.core.enums.ColumnRefTypeEnum;
import com.un.ebs.core.enums.DefaultFieldEnum;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.metadata.Query;
import com.un.ebs.core.util.DateUtils;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.handler.HandlerDbContext;
import com.un.ebs.sys.domain.Column;
import com.un.ebs.sys.domain.Table;
import com.un.ebs.sys.mapper.ColumnMapper;
import com.un.ebs.sys.mapper.TableMapper;
import com.un.ebs.sys.service.impl.DbHandler;
import com.un.ebs.sys.service.impl.TableWapper;
import com.un.ebs.sys.uitl.PoolUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author zc
 * @ClassName DbServiceImpl
 * @Description dbservice实现
 * @Date 2021/1/12
 */
@Service
@Slf4j
public class DbServiceImpl extends DbHandler implements DbService {

    @Autowired
    private ColumnMapper columnMapper;

    @Autowired
    private TableMapper tableMapper;

    @Autowired
    private HandlerDbContext handlerDbContext;

    @Autowired
    private DataSourceService dataSourceService;

    @Autowired
    private RelService relService;

    static String PK_ID = "id"; // 约定的返回主键的名称字段
    static String REF_PREFIX = "ref_";
    static String OPT_TY = "__type__"; // 操作字段
    static String OPT_TY_ADD = "add"; // 操作类型

    @Override
    public Page query(Query query) {
        TableView table = queryTableById(query.getObjectName());

        // 支持租户
//        List<QueryCondition> conditions = query.getConditions();
//        if (table.getSupportTenant()) {
//            QueryCondition condition = new QueryCondition();
//            condition.setKey(DefaultFieldEnum.tenant_id.getValue()); // "tenant_id"
//            condition.setOperator(String.valueOf(OperatorEnum.TYPE_EQ.getCode()));
//            condition.setValues(Arrays.asList(SecurityUtils.getTenantId()));
//            conditions.add(condition);
//        }

        SQLStrategy sqlStrategy = handlerDbContext.getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String querySQL = sqlStrategy.querySQL(table.getTableName(), query, table.getColumns());
        String queryCountSQL = sqlStrategy.queryCount(table.getTableName(), query, table.getColumns());

        Page page = new Page(query.getPageIndex(), query.getPageSize());
        // 求出total
        int total = 0;

        List<Map<String, Object>> retCount = executeQuery(queryCountSQL, PoolUtils.getConnection(table.getDataSource()));
        for (Map.Entry<String, Object> m : retCount.get(0).entrySet()) {
            total = ((Number) m.getValue()).intValue();
        }
        page.setTotal(total);


        if (total == 0) {
            page.setRecords(Collections.EMPTY_LIST);
            return page;
        }

        JSONArray jsonArray = new JSONArray();
        try {
            List<Map<String, Object>> list = executeQuery(querySQL, PoolUtils.getConnection(table.getDataSource()));
            for (int i = 0; i < list.size(); i++) {
                JSONObject jsonO = new JSONObject();
                for (Map.Entry<String, Object> m : list.get(i).entrySet()) {
                    jsonO.put(m.getKey(), m.getValue());
                }
                jsonArray.add(jsonO);
            }

            page.setRecords(jsonArray);
        } catch (Exception e) {
            e.printStackTrace();
        }

        log.info("queryCountSQL:" + queryCountSQL);
        log.info("querySQL:" + querySQL);
        return page;
    }

    @Override
    public JSONArray list(String bo, String sortName, Map<String, Object> params) {

        TableView table = queryTableById(bo);
        if(params == null){
            params = new HashMap<>();
        }

        // 支持租户
        if (table.getSupportTenant()) {
            String tenantId = SecurityUtils.getTenantId();
            params.put(DefaultFieldEnum.tenant_id.getValue(), tenantId);
        }

        SQLStrategy sqlStrategy = handlerDbContext.getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String listSQL = sqlStrategy.listSQL(table.getTableName(), sortName, params, table.getColumns());

        JSONArray jsonArray = new JSONArray();

        try {
            List<Map<String, Object>> list = executeQuery(listSQL, PoolUtils.getConnection(table.getDataSource()));
            if (list == null || list.size() <= 0) {
                return jsonArray;
            }

            for (int i = 0; i < list.size(); i++) {
                JSONObject jsonO = new JSONObject();
                for (Map.Entry<String, Object> m : list.get(i).entrySet()) {
                    jsonO.put(m.getKey(), m.getValue());
                }
                jsonArray.add(jsonO);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 4.返回结果
        return jsonArray;
    }

    @Override
    public Page pageList(String bo, String sortName, Integer pageIndex, Integer pageSize, Map<String, Object> params) {
        if (pageIndex <= 0) {
            throw new BusinessException("页面必须从 1 开始。");
        }
        TableView table = queryTableById(bo);

        // 支持租户
        if (table.getSupportTenant()) {
            String tenantId = SecurityUtils.getTenantId();
            if (params == null) {
                params = new HashMap<>();
            }
            params.put(DefaultFieldEnum.tenant_id.getValue(), tenantId);
        }

        SQLStrategy sqlStrategy = handlerDbContext.getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String pageListCountSQL = sqlStrategy.pageListCount(table.getTableName(), sortName, params, table.getColumns());

        Page page = new Page(pageIndex, pageSize);
        // setTotal
        log.info("pageList: " + pageListCountSQL);
        List<Map<String, Object>> retCount = executeQuery(pageListCountSQL, PoolUtils.getConnection(table.getDataSource()));
        int total = ((Number) retCount.get(0).entrySet().stream().findFirst().get().getValue()).intValue();
        log.info(String.format("==>Total: %d", total));

        if (total == 0) {
            page.setRecords(Collections.EMPTY_LIST);
            return page;
        }
        page.setTotal(total);

        // setRecords
        String pageListSQL = sqlStrategy.pageListSQL(table.getTableName(), sortName, pageIndex * pageSize - pageSize + 1, pageIndex * pageSize, params, table.getColumns());
        log.info("pageList:" + pageListSQL);
        List<Map<String, Object>> list = executeQuery(pageListSQL, PoolUtils.getConnection(table.getDataSource()));
        page.setRecords(list);

        return page;
    }

    @Override
    public JSONObject getById(String bo, String id) {
        TableView table = queryTableById(bo);
        SQLStrategy sqlStrategy = handlerDbContext.getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String getByIdSQL = sqlStrategy.getById(table.getTableName(), id, table.getColumns());

        JSONObject ret = new JSONObject();
        List<Map<String, Object>> list = executeQuery(getByIdSQL, PoolUtils.getConnection(table.getDataSource()));
        log.info("getByIdSQL:" + getByIdSQL);

        if (list.size() > 1) {
            throw new BusinessException("找到多笔数据。");
        }
        if (list.size() <= 0) {
            return ret;
        }

        for (Map.Entry<String, Object> m : list.get(0).entrySet()) {
            ret.put(m.getKey(), m.getValue());
        }

        return ret;
    }

    @Override
    public JSONObject add(String bo, JSONObject json) {
        TableView table = this.queryTableById(bo);
//        DataSource dataSource = this.getDataSourceById(table.getDataSourceId());
//        List<Column> columnList = this.getColumnListByTableId(table.getId());

        if (StringUtils.isNullOrEmpty(json.getString("id"))) {
            json.put("id", UUID.fastUUID().toString().replaceAll("-", ""));
        }

        // 支持租户
        if (table.getSupportTenant()) {
            String tenantId = SecurityUtils.getTenantId();
            json.put(DefaultFieldEnum.tenant_id.getValue(), tenantId);
        }
        if (table.getSupportOperationLog()) {
            json.put(DefaultFieldEnum.create_user_id.getValue(), SecurityUtils.getUserContent().getId());
            json.put(DefaultFieldEnum.create_person_name.getValue(), SecurityUtils.getUserContent().getPersonnelName());
            json.put(DefaultFieldEnum.create_time.getValue(), DateUtils.formatDate(new Date()));
        }
        if (table.getSupportAudit()) {
            json.put(DefaultFieldEnum.submit_status.getValue(), 0);
            json.put(DefaultFieldEnum.audit_status.getValue(), 0);
        }

        SQLStrategy sqlStrategy = handlerDbContext.getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String addSQL = sqlStrategy.add(table.getTableName(), json, table.getColumns());
        log.info("addSQL:" + addSQL);
        int row = 0;
        row = executeUpdate(addSQL, PoolUtils.getConnection(table.getDataSource()));

        JSONObject resultJson = new JSONObject();
        resultJson.put("row_count", row);
        resultJson.put("id", json.getString("id"));
        return resultJson;
    }

    @Override
    public JSONObject update(String bo, JSONObject json) {
        if (json == null || StringUtils.isNullOrEmpty(json.getString("id"))) {
            throw new BusinessException("参数不能为空，或者id不能为空");
        }
        TableView table = queryTableById(bo);
        //DataSource dataSource = this.getDataSourceById(table.getDataSourceId());
        List<Column> columnList = table.getColumns();

        // 支持租户
        if (table.getSupportTenant()) {
            String tenantId = SecurityUtils.getTenantId();
            columnList = columnList.stream().map(x -> {
                x.setId(null); // 清空id
                if (DefaultFieldEnum.tenant_id.getValue().equals(x.getColumnName())) {
                    x.setId(tenantId);
                }
                return x;
            }).collect(Collectors.toList());
        }

        SQLStrategy sqlStrategy = handlerDbContext
                .getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String updateSQL = sqlStrategy.update(table.getTableName(), json, columnList);
        int row = 0;
        log.info("updateSQL:" + updateSQL);
//        try {
        row = executeUpdate(updateSQL, PoolUtils.getConnection(table.getDataSource()));
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }

        JSONObject resultJson = new JSONObject();
        resultJson.put("row_count", row);
        return resultJson;
    }

    @Override
    public JSONObject delete(String bo, String id) {
        TableView table = queryTableById(bo);

        if (StringUtils.isNullOrEmpty(id)) {
            throw new BusinessException("bo实体id不能为空");
        }

        if (table.getSupportLogicDelete() == null) {
            throw new BusinessException("bo实体逻辑删除字段不能为空");
        }

        //DataSource dataSource = this.getDataSourceById(table.getDataSourceId());

        // 支持租户
        String tenantId = null;
        if (table.getSupportTenant()) {
            tenantId = SecurityUtils.getTenantId();
        }

        SQLStrategy sqlStrategy = handlerDbContext
                .getDbCommonStrategy(table.getDataSource().getDbType().getDesc());
        String deleteSQL = sqlStrategy.delete(table.getTableName(), id, table.getSupportLogicDelete(), tenantId);
        log.info("deleteSQL:" + deleteSQL);
        int row = 0;
//        try {
        row = executeUpdate(deleteSQL, PoolUtils.getConnection(table.getDataSource()));
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
        JSONObject resultJson = new JSONObject();
        resultJson.put("row_count", row);
        return resultJson;
    }

    @Override
    public JSONObject addComplexObject(String bo, JSONObject json) {
        JSONObject resultJson = new JSONObject();
        Map<String, Object> paraMap = new HashMap<>(); // 主表字段

        // 处理主对象
        json.entrySet().stream().filter(s -> !s.getKey().startsWith(REF_PREFIX)).forEach(s -> paraMap.put(s.getKey(), s.getValue()));

        // 父级id
        String refId = UUID.fastUUID().toString();
        paraMap.put(PK_ID, refId);
        // 新增主对象
        if (paraMap != null && !paraMap.isEmpty()) {
            JSONObject rootObj = new JSONObject(paraMap);
            resultJson = this.add(bo, rootObj); // 新增顶层对象
            String s = resultJson.getString(PK_ID); // 获取主键
            log.info("s=" + s);
        }

        // 处理子对象
        Map<String, Object> mapRef = json.entrySet().stream().filter(x -> x.getKey().startsWith(REF_PREFIX))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        for (Map.Entry<String, Object> entry : mapRef.entrySet()) {
            String key = entry.getKey();
            JSONArray jsonArray = json.getJSONArray(key); // JSONObject中的数组提取为JSONArray
            // JSONArray jsonArray =
            // JSONArray.parseArray(JSON.toJSONString(entry.getValue()));

            // 新增子对象
            Map<String, List<JSONObject>> datas = procComplexObject(key, jsonArray, refId);
            if (datas != null && !datas.isEmpty()) {
                for (Map.Entry<String, List<JSONObject>> en : datas.entrySet()) {
                    List<JSONObject> list = en.getValue();
                    for (JSONObject foo : list) {
                        this.add(en.getKey(), foo); // 新增子级对象
                    }
                }
            }
        }

        return resultJson;
    }

    /**
     * 新增-处理嵌套的对象
     *
     * @param key
     * @param jsonArray
     */
    private Map<String, List<JSONObject>> procComplexObject(String key, JSONArray jsonArray, String refId) {
        Map<String, List<JSONObject>> maps = new LinkedHashMap<>();
        // Map<String, String> refIdMap = new HashMap<>(); // Map<bo,refId>
        Queue<JSONArray> quene = new LinkedList<JSONArray>(); // 创建一个队列
        quene.offer(jsonArray);

        String innerKey = key; // 键值
        String innerRefId = refId;
//		if (refId != null) {
//			innerRefId = refId;
//		}
        Queue<String> refQuene = new LinkedList<String>(); // 创建一个队列存储父级id，该队列与上面的quene队列元素顺序保持一致；
        refQuene.offer(innerRefId);

        // refIdMap.put(key, innerRefId);
        while (!quene.isEmpty()) {// 如果队列不为空
            JSONArray obj = quene.poll(); // 从队列中获取一个File
            String rrrrfid = refQuene.poll();
            log.info("################## innerKey=" + innerKey + "," + obj.toJSONString());
            // 处理ref关键字
            String[] strArr = innerKey.split("\\|"); // 以竖分割
            String bo = strArr[0].substring(REF_PREFIX.length()); // bo名称
            String refColunm = strArr[1];
//			innerRefId = refIdMap.get(innerKey);
//			if (innerRefId == null) {
//				innerRefId = UUID.fastUUID().toString();
//				refIdMap.put(bo, innerRefId);
//			}
            JSONObject boJson = new JSONObject();
            for (int j = 0; j < obj.size(); j++) {
                String pk_id = UUID.fastUUID().toString();
                boJson.put(PK_ID, pk_id); // 主键赋值
                boJson.put(refColunm, rrrrfid); // 外键赋值
                JSONObject innerObject = obj.getJSONObject(j);
                for (Map.Entry<String, Object> entry2 : innerObject.entrySet()) {
                    if (entry2.getKey().startsWith(REF_PREFIX)) { // 外键-指向的复合对象
                        log.info("################## aaaKey=" + entry2.getKey());
                        innerKey = entry2.getKey(); // 切换key
                        JSONArray aaa = innerObject.getJSONArray(entry2.getKey()); // JSONObject中的数组提取为JSONArray
                        quene.offer(aaa); // 存储到队列中
                        refQuene.offer(pk_id);
                    } else {
                        boJson.put(entry2.getKey(), entry2.getValue());
                        log.info(entry2.getKey() + "=" + entry2.getValue());
                    }
                }

                List<JSONObject> datas = maps.get(bo);
                if (datas == null) {
                    datas = new ArrayList<>();
                }

                JSONObject copy = JSONObject.parseObject(boJson.toJSONString());
                // this.add(bo, copy);
                datas.add(copy); // 重新一个对象add到集合
                maps.put(bo, datas);
                boJson.clear(); // 清空
            }

        }

        return maps;
    }

    @Override
    public JSONObject updateComplexObject(String bo, JSONObject json) {
        JSONObject resultJson = new JSONObject();
        Map<String, Object> paraMap = new HashMap<>(); // 主表字段
        // 处理主对象
        Map<String, Object> mapMain = json.entrySet().stream().filter(x -> !x.getKey().startsWith(REF_PREFIX))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        for (Map.Entry<String, Object> entry : mapMain.entrySet()) {
            paraMap.put(entry.getKey(), entry.getValue());
        }
        // 处理主对象
        if (paraMap != null && !paraMap.isEmpty()) {
            JSONObject rootObj = new JSONObject(paraMap);
            resultJson = this.update(bo, rootObj); // 更新顶层对象
            log.info("s=" + resultJson);
        }
        // 父级id
        String refId = paraMap.get(PK_ID).toString();
        // 处理删除
        procDelNestObject(bo, json);
        // 处理子对象新增和更i性能
        Map<String, Object> mapRef = json.entrySet().stream().filter(x -> x.getKey().startsWith(REF_PREFIX))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        for (Map.Entry<String, Object> entry : mapRef.entrySet()) {
            String key = entry.getKey();
            JSONArray jsonArray = json.getJSONArray(key); // JSONObject中的数组提取为JSONArray
            Map<String, List<JSONObject>> datas = procUpdateComplexObject(key, jsonArray, refId);
            if (datas != null && !datas.isEmpty()) {
                /* 处理新增和更新 */
                // String pk_id = ""; // 主键id
                for (Map.Entry<String, List<JSONObject>> en : datas.entrySet()) {
                    // String enKey = en.getKey();
                    List<JSONObject> list = en.getValue();
                    for (JSONObject foo : list) {
                        // 获取主键id：如果为空则是新增，不为空则是更新
                        // pk_id = foo.getString(PK_ID);
                        String optType = foo.getString(OPT_TY);
                        if (OPT_TY_ADD.equals(optType)) {
                            this.add(en.getKey(), foo); // 新增子级对象
                        } else {
                            this.update(en.getKey(), foo); // 更新子级对象
                        }
                    }
                }
            }
        }

        return resultJson;
    }

    /**
     * 更新-处理嵌套对象
     *
     * @param key       bo名称
     * @param jsonArray json数据
     * @param refId     外键的值
     */
    private Map<String, List<JSONObject>> procUpdateComplexObject(String key, JSONArray jsonArray, String refId) {
        Map<String, List<JSONObject>> maps = new LinkedHashMap<>();
        Queue<JSONArray> quene = new LinkedList<JSONArray>(); // 创建一个队列
        quene.offer(jsonArray);

        Queue<String> keyQuene = new LinkedList<String>(); // 创建一个键的队列
        keyQuene.offer(key);

        Queue<String> refQuene = new LinkedList<String>(); // 创建一个队列存储父级id，该队列与上面的quene队列元素顺序保持一致；
        refQuene.offer(refId);

        // String innerKey = key; // 键值
        while (!quene.isEmpty()) {// 如果队列不为空
            JSONArray obj = quene.poll(); // 从队列中获取一个File
            String innerKey = keyQuene.poll();
            String rrrrfid = refQuene.poll(); // 外键id
            log.info("################## innerKey=" + innerKey + "," + obj.toJSONString());
            // 处理ref关键字
            String bo = innerKey;
            String refColunm = "";
            if (innerKey.startsWith(REF_PREFIX)) {
                String[] strArr = innerKey.split("\\|"); // 以竖分割
                bo = strArr[0].substring(REF_PREFIX.length()); // bo名称
                refColunm = strArr[1];
            }
            JSONObject boJson = new JSONObject();
            for (int j = 0; j < obj.size(); j++) {
                JSONObject innerObject = obj.getJSONObject(j);
                String pk_id = innerObject.getString(PK_ID);
                if (org.apache.commons.lang.StringUtils.isBlank(pk_id)) {// 主键id为空或者空字符串，则需要新增
                    pk_id = UUID.fastUUID().toString();
                    boJson.put(PK_ID, pk_id); // 构造主键列并赋值
                    boJson.put(OPT_TY, OPT_TY_ADD); // 新增的标记
                    boJson.put(refColunm, rrrrfid); // 构造外键并赋值
                }
                for (Map.Entry<String, Object> entry2 : innerObject.entrySet()) {
                    if (entry2.getKey().startsWith(REF_PREFIX)) { // 外键-指向的复合对象
                        log.info("################## aaaKey=" + entry2.getKey());
                        // innerKey = entry2.getKey(); // 切换key
                        JSONArray aaa = innerObject.getJSONArray(entry2.getKey()); // JSONObject中的数组提取为JSONArray
                        quene.offer(aaa); // 存储到队列中
                        keyQuene.offer(entry2.getKey()); // 外键名称
                        refQuene.offer(pk_id); // 父级id
                    } else {
                        boJson.put(entry2.getKey(), entry2.getValue());
                        log.info(entry2.getKey() + "=" + entry2.getValue());
                    }
                }

                // 如果不包含id，则是新增，需要构造外键列；更新的话，不更新外键列；
//				if (!boJson.containsKey(PK_ID)) {
//					boJson.put(refColunm, rrrrfid);
//				}

                List<JSONObject> datas = maps.get(bo);
                if (datas == null) {
                    datas = new ArrayList<>();
                }

                JSONObject copy = JSONObject.parseObject(boJson.toJSONString());
                datas.add(copy); // 重新一个对象add到集合
                maps.put(bo, datas);
                boJson.clear(); // 清空
            }
        }

        return maps;
    }

    /**
     * 更新-处理将要删除的对象
     *
     * @param tableId
     * @param json
     * @return
     */
    private void procDelNestObject(String tableId, JSONObject json) {
        List<Table> tables = relService.getDbTables(null);
        Table table = relService.getTableById(tableId);

        TableWapper tableWapper = new TableWapper(); // 子类转父类
        tableWapper.setId(table.getId());
        tableWapper.setTableName(table.getTableName());
        tableWapper.setParentId(table.getParentId());
        relService.recursiveTable(tableWapper, tables, tableId);

        procDel(tableWapper, json);
    }

    /**
     * 处理删除 <br>
     * 情况：<br>
     * 1、子元素节点没有 查询所有子元素，删除。 <br>
     * 2、父元素节点没有 递归查询所有子元素，删除。 <br>
     * 3、子元素少一项 数据对比，确定要删除的。<br>
     * <p>
     * 实现思路： <br>
     * 1、遍历TableWapper，形成List<TableWapper> A;<br>
     * 2、递归json，形成Map<String,List<JSONObject>> B； <br>
     * 3、遍历A，判断在B中有没有对应的Key;<br>
     * 有对应的key：证明节点存在，则对比子元素，看删除了哪一条； <br>
     * 没有对应的key： 是子元素（子表），处理情况1； 是父元素（父表），处理情况2；<br>
     */
    private void procDel(TableWapper tableWapper, JSONObject json) {
        // 所有表
        List<TableWapper> tables = getTabelsParentToChild(tableWapper);
        // 所有数据
        JSONArray jsonArray = new JSONArray();
        jsonArray.add(json); // jsonArray添加jsonObject
        String refId = json.getString(PK_ID);
        Map<String, List<JSONObject>> datas = procUpdateComplexObject(tableWapper.getId(), jsonArray, refId);

        Set<String> deledset = new HashSet<>(); // 已经删除的表集合
        for (TableWapper table : tables) {
            if (table.getParentId() == null) { // 如果是顶层表，则不处理，继续循环。不能调用更新接口进行删除顶层对象
                continue;
            }

            if (deledset.contains(table.getId())) { // 存在联级删除的情况，如果该表已经被删除，则不处理，继续循环
                continue;
            }

            boolean flag2 = false;
            if (datas.containsKey(table.getId())) {// 存在key
                // 比较集合
                List<JSONObject> reqDatas = datas.get(table.getId());
                List<JSONObject> dbDatas = new ArrayList<>();
                JSONArray array = this.list(table.getId(), PK_ID, null);
                for (int i = 0; i < array.size(); i++) {
                    dbDatas.add(array.getJSONObject(i));
                }
                if (reqDatas == null || reqDatas.isEmpty()) {// 请求结点下没有数据
                    flag2 = true;
                } else {// 请求节点有数据
                    for (JSONObject foo : dbDatas) {
                        String pk_id = foo.getString(PK_ID);
                        boolean exists = false;
                        for (JSONObject poo : reqDatas) {
                            String pk_id_2 = poo.getString(PK_ID);
                            if (pk_id_2 != null && pk_id.equals(pk_id_2)) {
                                exists = true;
                                break;
                            }
                        }
                        if (exists == false) {
                            this.delete(table.getId(), pk_id);
                        }
                    }
                }

                // 这里只考虑少的情况（删除）
                // 差集

                /*
                 * List<JSONObject> cjList = dbDatas.stream() .filter(item -> (reqDatas != null
                 * && !reqDatas.contains(item))).collect(Collectors.toList()); if (cjList !=
                 * null && !cjList.isEmpty()) { for (JSONObject foo : cjList) {
                 * this.delete(table.getId(), foo.getString(PK_ID)); } }
                 */

            } else {// 不存在key
                flag2 = true;
            }

            if (flag2 == true) {
                deledset.add(table.getId());
                List<TableWapper> childToparentTables = getTabelsChildToParent(table); // 递归子级所有的表
                if (childToparentTables != null && !childToparentTables.isEmpty()) {
                    for (TableWapper child : childToparentTables) {
                        JSONArray array = this.list(child.getId(), PK_ID, null);
                        for (int i = 0; i < array.size(); i++) {
                            this.delete(child.getId(), array.getJSONObject(i).getString(PK_ID));
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取table列表（从父到子）
     *
     * @param tableWapper 父级表
     * @return
     */
    private List<TableWapper> getTabelsParentToChild(TableWapper tableWapper) {
        List<TableWapper> tables = new ArrayList<>();
        Queue<TableWapper> quene = new LinkedList<TableWapper>(); // 创建一个队列
        quene.offer(tableWapper);
        while (!quene.isEmpty()) {// 如果队列不为空
            TableWapper obj = quene.poll(); // 从队列中获取一个File
            log.info("################## tableId=" + obj.getId() + ",tableName=" + obj.getTableName());
            List<TableWapper> childs = obj.getChilds();
            if (childs != null && !childs.isEmpty()) {
                for (TableWapper tb : childs) {
                    quene.offer(tb);
                }
            }
            tables.add(obj);
        }

        return tables;
    }

    /**
     * 获取table列表（从子到子父）
     *
     * @param tableWapper 父级表
     * @return
     */
    private List<TableWapper> getTabelsChildToParent(TableWapper tableWapper) {
        List<TableWapper> tables = new ArrayList<>();
        Stack<TableWapper> stack = new Stack<TableWapper>();
        Queue<TableWapper> quene = new LinkedList<TableWapper>(); // 创建一个队列
        quene.offer(tableWapper);
        while (!quene.isEmpty()) {// 如果队列不为空
            TableWapper obj = quene.poll(); // 从队列中获取一个File
            log.info("################## tableId=" + obj.getId() + ",tableName=" + obj.getTableName());
            List<TableWapper> childs = obj.getChilds();
            if (childs != null && !childs.isEmpty()) {
                for (TableWapper tb : childs) {
                    quene.offer(tb);
                }
            }
            stack.push(obj);
        }

        while (!stack.empty()) {
            tables.add(stack.pop());
        }
        return tables;
    }

    @Override
    public JSONObject getComplexObjectById(String bo, String id) {
        JSONObject mainObject = this.getById(bo, id); // 查询主对象

        List<Table> tables = relService.getDbTables(null);
        Table table = relService.getTableById(bo);

        // 获取表间关系
        TableWapper tableWapper = new TableWapper(); // 子类转父类
        tableWapper.setId(table.getId());
        tableWapper.setTableName(table.getTableName());
        tableWapper.setParentId(table.getParentId());
        relService.recursiveTable(tableWapper, tables, bo);

        Map<String, Object> params = new HashMap<>(); // 查询参数
        // 表关系队列（维持进出队列与父对象队列顺序一致）
        Queue<TableWapper> quene = new LinkedList<TableWapper>();
        quene.offer(tableWapper);

        // 父对象队列（维持进出队列与表关系队列顺序一致）
        Queue<JSONObject> parentQuene = new LinkedList<JSONObject>();
        parentQuene.offer(mainObject);

        while (!quene.isEmpty()) {// 如果队列不为空
            params.clear(); // 清空查询参数
            TableWapper obj = quene.poll(); // 从队列中获取一个对象
            JSONObject parentObj = parentQuene.poll();
            log.info("################## tableId=" + obj.getId() + ",tableName=" + obj.getTableName());
            List<TableWapper> childs = obj.getChilds();
            if (childs != null && !childs.isEmpty()) {
                for (TableWapper tb : childs) {
                    // 获取子表的所有字段
                    LambdaQueryWrapper<Column> qw = Wrappers.lambdaQuery();
                    qw.eq(Column::getTableId, tb.getId());
                    List<Column> columns = columnMapper.selectList(qw);
                    // 查出与父级表名一样的外键字段名称集合
                    Optional<Column> ref = columns.stream()
                            .filter(x -> (x.getRefTableName() != null && x.getRefTableName().equals(obj.getTableName()))
                                    && (x.getRefType() != null && ColumnRefTypeEnum.FK.equals(x.getRefType()))
                                    && x.getRefColumnName() != null)
                            .findFirst();
                    String refColumnName = ref.get().getRefColumnName(); // 指向主表的字段
                    String columnName = ref.get().getColumnName(); // 外键列
                    String parentPkId = parentObj.getString(refColumnName);
                    log.info("parentPkId=" + parentPkId);

                    // 组装查询子对象列表参数
                    params.put(columnName, parentPkId);
                    JSONArray jsonArray = this.list(tb.getId(), null, params);
                    if (jsonArray != null && jsonArray.size() > 0) {
                        // 格式：ref_32cbe010e990355a9e4fa8389a778ff8|order_id
                        String jsonFeild = String.format("%s%s|%s", REF_PREFIX, tb.getId(), columnName);
                        parentObj.put(jsonFeild, jsonArray); // 将JsonArray添加到JsonObject

                        // 遍历jsonArray
                        for (int i = 0; i < jsonArray.size(); i++) {
                            JSONObject object = jsonArray.getJSONObject(i);
                            object.remove(columnName); // 删除外键列

                            quene.offer(tb);
                            parentQuene.offer(object);
                        }
                    }
                }
            }
        }

        return mainObject;
    }

    private TableView queryTableByName(String tableName) {
        LambdaQueryWrapper<Table> lq = Wrappers.lambdaQuery();
        lq.eq(Table::getTableName, tableName);
        List<Table> list = tableMapper.selectList(lq);

        if (list.size() == 1) {
            return queryTableById(list.get(0).getId());
        } else {
            throw new BusinessException("找到 " + list.size() + " 个表。");
        }
    }

    private TableView queryTableById(String id) {
        TableView obj = new TableView(tableMapper.selectById(id));
        obj.setDataSource(dataSourceService.getById(obj.getDataSourceId()));
        obj.setColumns(columnMapper.selectByTableId(id));
        return obj;
    }
}
